package com.changanw.account.service;

import com.changanw.account.mapper.AccountMapper;
import com.changanw.account.model.Account;
import io.seata.rm.tcc.api.BusinessActionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

@Service
public class AccountService {
    private static Logger logger =  LoggerFactory.getLogger(AccountService.class);
    @Autowired
    AccountMapper accountMapper;

    /**
     * 这里实际上就是准备工作，也是分布式事务一阶段的工作
     * 这个时候主要去检查一下账户是否存在，。检查一下余额是否充足，把要扣的钱先冻结起来
     * @param userId
     * @param money
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean prepare(String userId, Double money) {
        Account account = accountMapper.getAccountByUserId(userId);
        if (account == null) {
            throw new RuntimeException("账户不存在");
        }
        if (account.getMoney() < money) {
            throw new RuntimeException("账户余额不足，预扣款失败");
        }
        //先把钱冻结起来
        account.setFreezeMoney(account.getFreezeMoney() + money);
        account.setMoney(account.getMoney() - money);
        Integer i = accountMapper.updateAccount(account);
        logger.info("{} 账户预扣款 {} 元", userId, money);
        return i == 1;
    }

    /**
     * 第二阶段的提交操作
     * 实际扣款阶段
     * @param context
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean commit(BusinessActionContext context) {
        //获取prepare中的参数
        String userId = (String) context.getActionContext("userId");
        Double money = ((BigDecimal) context.getActionContext("money")).doubleValue();
        Account account = accountMapper.getAccountByUserId(userId);
        if (account.getFreezeMoney() < money){
            throw new RuntimeException("账户余额不足，扣款失败");
        }
        account.setFreezeMoney(account.getFreezeMoney()-money);
        Integer integer = accountMapper.updateAccount(account);
        logger.info("{} 账户扣款 {} 元", userId, money);
        return 1 == integer;
    }

    /**
     * 二阶段回滚，主要是把冻结的钱释放
     * @param context
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean rollback(BusinessActionContext context) {
        String userId = (String) context.getActionContext("userId");
        Double money = ((BigDecimal) context.getActionContext("money")).doubleValue();
        Account account = accountMapper.getAccountByUserId(userId);
        if (account.getFreezeMoney() >= money){
            account.setMoney(account.getMoney() + money);
            account.setFreezeMoney(account.getFreezeMoney()-money);
            Integer integer = accountMapper.updateAccount(account);
            logger.info("{} 金额释放 {} 元", userId, money);
            return integer == 1;
        }
        logger.info("{} 金额释放", userId);
        return true;
    }
}
